#include "cSprite.h"

cEffectPtr cSprite::SpriteShader;

cSprite::cSprite() : 
	Position(0.0f, 0.0f), Rotation(0.0f), Scale(1.0f, 1.0f), MaskColor(1.0f, 1.0f, 1.0f, 1.0f), texture(nullptr)
{
	LoadShader();
	CreateBuffers(D3DXVECTOR2(0.0f, 0.0f), D3DXVECTOR2(1.0f, 1.0f));
}

cSprite::cSprite( const std::wstring & FileName, D3DXVECTOR2 & TexCoordLeftTop /*= Vector2D(0.0f, 0.0f)*/, D3DXVECTOR2 & TexCoordRightBottom /*= D3DXVECTOR2(1.0f, 1.0f)*/ ) :
	Position(0.0f, 0.0f), Rotation(0.0f), Scale(1.0f, 1.0f), MaskColor(1.0f, 1.0f, 1.0f, 1.0f)
{
	LoadShader();
	CreateBuffers(TexCoordLeftTop, TexCoordRightBottom);
	texture = cGraphicsEngine::GetInstance().LoadTexture(FileName);
	SetScale(D3DXVECTOR2(1.0f, 1.0f));
}

cSprite::~cSprite()
{
	cGraphicsEngine::GetInstance().ResetPipeline();
}

void cSprite::Draw()
{
	if(!texture)
		return;

	D3DXMATRIX mat, scale, pos, rot;
	D3DXMatrixTranslation(&pos, Position.x, Position.y, 0.0f);
	D3DXMatrixScaling(&scale, Scale.x, Scale.y, 0.0f);
	D3DXMatrixRotationZ(&rot, Rotation);
	mat = (scale * rot * pos) * *cGraphicsEngine::GetInstance().GetMatrixPointer(MatrixOrtho);

	cGraphicsEngine::GetInstance().BindShader(SpriteShader);
	cGraphicsEngine::GetInstance().SetMatrixConstant("matRes", &mat);
	cGraphicsEngine::GetInstance().BindTexture(texture, "Texture");
	cGraphicsEngine::GetInstance().SetVectorConstant("MaskColor", &MaskColor);
	SpriteShader.GetData()->Pass->Apply(0);
	spriteMesh.Draw(cGraphicsEngine::GetInstance().GetDevicePointer());
}

void cSprite::SetTexture( cTexturePtr ptr )
{
	texture = ptr;

	if(ptr)
		SetScale(D3DXVECTOR2(1.0f, 1.0f));
}

void cSprite::SetPosition( D3DXVECTOR2 & pos )
{
	Position = pos;
}

void cSprite::SetRotation( float rot )
{
	Rotation = rot;
}

void cSprite::SetScale( D3DXVECTOR2 & sc )
{
	Scale = sc;

	if(!texture)
		return;

	Scale.x *= texture->width;
	Scale.y *= texture->height;
}

D3DXVECTOR2 cSprite::GetTextureDimensions() const
{
	return D3DXVECTOR2((float)texture->width, (float)texture->height);
}

void cSprite::SetMaskColor( D3DXVECTOR4 & color )
{
	MaskColor = color;
}

void cSprite::CreateBuffers( D3DXVECTOR2 & LT, D3DXVECTOR2 & RB )
{
	MeshData * temp = new MeshData;
	spriteMesh.SetData(std::shared_ptr<MeshData>(temp));
	spriteMesh.GetData()->indicesCount = 6;
	spriteMesh.GetData()->verticesCount = 4;
	spriteMesh.GetData()->vertexSize = sizeof(SpriteVertex);
	//some buffer calculations here
	SpriteVertex ver[] = 
	{
		/*
		0        1
		*--------*
		|      / |
		|    /   |
		|  /     |
		|/       |
		*--------*
		2        3
		*/
		{D3DXVECTOR2(-0.5f, -0.5f),	D3DXVECTOR2(LT.x, LT.y)},
		{D3DXVECTOR2(0.5f, -0.5f),	D3DXVECTOR2(RB.x, LT.y)},
		{D3DXVECTOR2(-0.5f, 0.5f),	D3DXVECTOR2(LT.x, RB.y)},
		{D3DXVECTOR2(0.5f, 0.5f),	D3DXVECTOR2(RB.x, RB.y)},
	};
	long ind[6] = {0, 1, 2, 1, 3, 2};

	D3D10_BUFFER_DESC vbd;
	vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	vbd.ByteWidth = sizeof(SpriteVertex) * 4;
	vbd.CPUAccessFlags = 0;
	vbd.MiscFlags = 0;
	vbd.Usage = D3D10_USAGE_DEFAULT;

	D3D10_SUBRESOURCE_DATA vertexData;
	memset(&vertexData, 0, sizeof(D3D10_SUBRESOURCE_DATA));
	vertexData.pSysMem = ver;

	cGraphicsEngine::GetInstance().GetDevicePointer()->CreateBuffer(&vbd, &vertexData, &spriteMesh.GetData()->VertexBuffer);

	D3D10_BUFFER_DESC ibd;
	ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
	ibd.ByteWidth = sizeof(long) * 6;
	ibd.CPUAccessFlags = 0;
	ibd.MiscFlags = 0;
	ibd.Usage = D3D10_USAGE_DEFAULT;

	D3D10_SUBRESOURCE_DATA indexData;
	memset(&indexData, 0, sizeof(D3D10_SUBRESOURCE_DATA));
	indexData.pSysMem = ind;

	cGraphicsEngine::GetInstance().GetDevicePointer()->CreateBuffer(&ibd, &indexData, &spriteMesh.GetData()->IndexBuffer);
}

void cSprite::SetSizeInPixels( int x, int y )
{
	if(texture)
		SetScale(D3DXVECTOR2((float)texture->width / x, (float)texture->height / y));
}

void cSprite::LoadShader()
{
	if(SpriteShader.GetData() == nullptr)
	{
		std::vector<InputElement> input;
		input.push_back(InputElement("POSITION", 2));
		input.push_back(InputElement("TEXCOORD", 2));
		SpriteShader = cGraphicsEngine::GetInstance().LoadShader(L"SpriteShader.fx", input);
	}
}
